package funcInterface.consumer;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 在java的世界中，方法被看作是行为，而Function就是行为的一种抽象表述，
 * 它表示这样一种行为： 只有一个输入和一个输出的行为。
 * 行为的具体调用方式是： 行为对象.apply(行为接收的入参)
 */
public class FunctionTest {
    public static void main(String[] args) {
        FunctionTest functionTest = new FunctionTest();
        List<Person> persons = new ArrayList<Person>() {
            {
                add(new Person(20, "maomao"));
                add(new Person(30, "mayun"));
                add(new Person(26, "keke"));
                add(new Person(40, "angular"));
            }
        };
        System.out.println("-------------有一个需求：按照年龄给person排序--------------------");
        functionTest.sortByAge(persons).forEach(person -> System.out.println(person.getName() + "----" + person.getAge()));
        System.out.println("-------------需求变动：按照名字长度给人排序--------------------");
        functionTest.sortByNameLength(persons).forEach(person -> System.out.println(person.getName() + "----" + person.getAge()));
        System.out.println("--------------需求变动n多次，按照各种场景排序-------------------");
        System.out.println(".");
        System.out.println(".");
        System.out.println(".");
        System.out.println("----------------使用函数式接口Funcation，把具体的行为交给调用者-----------------");
        functionTest.sort(persons, personList -> personList
                .stream()
                .sorted(
                        (personA, personB) -> (int) personA.getName().charAt(0) < (int) personB.getName().charAt(0) ? -1 : 1
                )
                .collect(Collectors.toList())
        ).forEach(person -> System.out.println((int) person.getName().charAt(0) + "----" + person.getName() + "----" + person.getAge()));


        /**
         * 需求：
         *      执行行为A前先执行行为B（以下指示Before），其中A指代当前行为，即compose的触发者。
         *
         * compose语法解读：
         *      compose返回一个行为X。
         *
         * compose返回的行为X执行解读：
         *      在X行为调用apply时【x行为被执行】，入参是v，X行为的返回结果是行为A执行的返回值。
         *      执行行为A，入参是before行为的返回值，所以先执行before行为以获取入参，
         *      执行行为before【before行为被执行】，before的返回结果作用入参传入行为A,
         *      行为A被执行【行为A被执行】，最后行为A的执行结果被X行为返回出去。
         *
         * 总结：
         *      整个过程产生了三个行为，其中行为A和行为before是我们完成需求的必须行为，
         *      而行为X是触发我们需求的一个行为。
         */

        /**
         * 需求：
         *      执行完行为A后在执行after行为，其中A指代当前行为，即andThen的触发者。
         *
         * andThen语法解读：
         *      andThen返回一个行为X。
         *
         * andThen返回的行为X执行解读：
         *      在X行为调用apply时【x行为被执行】，入参是t，X行为的返回结果是行为after执行的返回值。
         *      执行行为after，入参是A行为的返回值，所以先执行A行为以获取入参，
         *      执行行为A【A行为被执行】，A的返回结果作用入参传入行为after,
         *      行为after被执行【行为after被执行】，最后行为after的执行结果被X行为返回出去。
         *
         * 总结：
         *      整个过程产生了三个行为，其中行为A和行为after是我们完成需求的必须行为，
         *      而行为X是触发我们需求的一个行为。
         */

        System.out.println("------compose和andThen  “输入的行为” 是在 “输入的行为” 执行前执行还是之后？");

        // 定义一个相加的行为，输入的行为是相乘
        Function<Integer, Integer> A_Action = (i) -> i + i;
        Function<Integer, Integer> Input_Action = (Integer i) -> i * i;

        System.out.println("------compose---------"); // compose表示先执行输入的行为，然后执行自己
        Function<Integer, Integer> X_Action1 = A_Action.compose(Input_Action);
        System.out.println(X_Action1.apply(2));

        System.out.println("------andThen---------");
        Function<Integer, Integer> X_Action2 = A_Action.andThen(Input_Action); // andThen表示先执行自己，然后执行输入的行为
        System.out.println(X_Action2.apply(2));

        // 完成需求的两个Action：
        System.out.println(A_Action);
        System.out.println(Input_Action);
        // 触发我们完成需求的Action：
        System.out.println(X_Action1);
        System.out.println(X_Action2);

    }

    /**
     * 按照年龄排序
     *
     * @param personList
     * @return
     */
    public List<Person> sortByAge(List<Person> personList) {
        return personList.stream().sorted((personA, personB) -> personA.getAge() < personB.getAge() ? -1 : 1).collect(Collectors.toList());
    }

    /***
     * 按照名字长度排序
     * @param personList
     * @return
     */
    public List<Person> sortByNameLength(List<Person> personList) {
        return personList.stream().sorted((personA, personB) -> personA.getName().length() < personB.getName().length() ? -1 : 1).collect(Collectors.toList());
    }

    /**
     * 把具体排序规则交由调用者
     *
     * @param personList
     * @param function
     * @return
     */
    public List<Person> sort(List<Person> personList, Function<List<Person>, List<Person>> function) {
        return function.apply(personList);
    }

}
